<template>
  <el-dialog
    :model-value="modelValue"
    :title="dialogTitle"
    width="1200px"
    append-to-body
    align-center
    @close="handleClose"
  >
    <!-- 选择状态显示 -->
    <div class="selection-info">
      <span>已关联项目: {{ linkedTotal }} 个</span>
      <span v-if="selectedLinkedProducts.length > 0"
        >（已选择 {{ selectedLinkedProducts.length }} 个待移除）</span
      >
      <span>新增关联: {{ globalSelectedAvailableProducts.size }} 个</span>
      <span class="selection-detail">
        总计:
        {{ linkedTotal + globalSelectedAvailableProducts.size - selectedLinkedProducts.length }}
        个项目
      </span>
    </div>

    <!-- 分组展示 -->
    <el-row :gutter="20">
      <!-- 已关联项目 -->
      <el-col :span="12">
        <div class="linked-products-section">
          <div class="section-header">
            <h3>{{ leftTableTitle }}</h3>
            <el-form ref="linkedQueryRef" :model="linkedQueryParams" class="search-form">
              <el-form-item>
                <el-input
                  v-model="linkedQueryParams[searchField]"
                  :placeholder="`搜索已关联${nameField}`"
                  clearable
                  style="width: 150px"
                  @keyup.enter="handleLinkedQuery"
                  @clear="handleLinkedQuery"
                />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" icon="Search" @click="handleLinkedQuery">查询</el-button>
              </el-form-item>
              <el-form-item>
                <el-button
                  type="danger"
                  icon="Delete"
                  :disabled="selectedLinkedProducts.length === 0"
                  @click="batchRemoveLinkedProducts"
                >
                  批量移除 ({{ selectedLinkedProducts.length }})
                </el-button>
              </el-form-item>
            </el-form>
          </div>

          <el-table
            v-loading="linkedLoading"
            :data="linkedProducts"
            max-height="400"
            class="linked-table"
            row-key="id"
            @selection-change="handleLinkedSelectionChange"
          >
            <el-table-column type="selection" width="50" align="center" />
            <template v-for="column in leftTableColumns" :key="column.prop">
              <el-table-column
                :label="column.label"
                :prop="column.prop"
                :width="column.width"
                :align="column.align || 'center'"
                :show-overflow-tooltip="column.showOverflowTooltip !== false"
              >
                <template #default="scope">
                  <slot :name="column.slot" :row="scope.row">
                    {{ scope.row[column.prop] }}
                  </slot>
                </template>
              </el-table-column>
            </template>
            <el-table-column label="操作" align="center" width="80">
              <template #default="scope">
                <el-button type="danger" link size="small" @click="removeLinkedProduct(scope.row)"
                  >移除</el-button
                >
              </template>
            </el-table-column>
          </el-table>

          <el-pagination
            v-show="linkedTotal > 0"
            v-model:current-page="linkedQueryParams.pageNum"
            v-model:page-size="linkedQueryParams.pageSize"
            :total="linkedTotal"
            :small="true"
            :layout="'total,sizes, prev, pager, next'"
            @size-change="getLinkedProducts"
            @current-change="getLinkedProducts"
          />
        </div>
      </el-col>

      <!-- 可关联项目 -->
      <el-col :span="12">
        <div class="available-products-section">
          <div class="section-header">
            <h3>{{ rightTableTitle }}</h3>
            <el-form ref="linkQueryRef" :model="linkQueryParams" class="search-form">
              <el-form-item>
                <el-input
                  v-model="linkQueryParams[searchField]"
                  :placeholder="`搜索可关联${nameField}`"
                  clearable
                  style="width: 150px"
                  @keyup.enter="handleLinkQuery"
                  @clear="handleLinkQuery"
                />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" @click="handleLinkQuery">查询</el-button>
              </el-form-item>
              <el-form-item>
                <el-button
                  type="primary"
                  icon="Link"
                  :disabled="globalSelectedAvailableProducts.size === 0"
                  @click="confirmLink"
                >
                  {{ confirmText }}({{ globalSelectedAvailableProducts.size }})
                </el-button>
              </el-form-item>
            </el-form>
          </div>

          <el-table
            ref="availableTableRef"
            v-loading="linkLoading"
            :data="availableProducts"
            class="available-table"
            row-key="id"
            @selection-change="handleLinkSelectionChange"
          >
            <el-table-column type="selection" width="50" align="center" />
            <template v-for="column in rightTableColumns" :key="column.prop">
              <el-table-column
                :label="column.label"
                :prop="column.prop"
                :width="column.width"
                :align="column.align || 'center'"
                :show-overflow-tooltip="column.showOverflowTooltip !== false"
              >
                <template #default="scope">
                  <slot :name="column.slot" :row="scope.row">
                    {{ scope.row[column.prop] }}
                  </slot>
                </template>
              </el-table-column>
            </template>
          </el-table>

          <el-pagination
            v-show="linkTotal > 0"
            v-model:current-page="linkQueryParams.pageNum"
            v-model:page-size="linkQueryParams.pageSize"
            :total="linkTotal"
            :small="true"
            :layout="'total,sizes, prev, pager, next'"
            @size-change="getAvailableProducts"
            @current-change="getAvailableProducts"
          />
        </div>
      </el-col>
    </el-row>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="cancelLink">取 消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, watch, nextTick, PropType } from "vue";
import {
  ElMessage,
  ElMessageBox,
  ElDialog,
  ElRow,
  ElCol,
  ElForm,
  ElFormItem,
  ElInput,
  ElButton,
  ElTable,
  ElTableColumn
} from "element-plus";

// Props
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  },
  targetId: {
    type: [String, Number],
    default: null
  },
  dialogTitle: {
    type: String,
    default: "关联管理"
  },
  leftTableTitle: {
    type: String,
    default: "已关联项目"
  },
  rightTableTitle: {
    type: String,
    default: "可关联项目"
  },
  confirmText: {
    type: String,
    default: "关联项目"
  },
  leftTableColumns: {
    type: Array as PropType<any[]>,
    default: () => []
  },
  rightTableColumns: {
    type: Array as PropType<any[]>,
    default: () => []
  },
  searchField: {
    type: String,
    default: "name"
  },
  idField: {
    type: String,
    default: "id"
  },
  // 显示搜索placeholder名称字段
  nameField: {
    type: String,
    default: "name"
  }
});

// Emits
const emit = defineEmits([
  "update:modelValue",
  "getLinkedItems",
  "getAvailableItems",
  "updateAssociation", // 保留原有事件以兼容
  "addAssociation", // 新增：添加关联事件
  "removeAssociation", // 新增：移除关联事件
  "confirm",
  "cancel"
]);

// Data
const linkedProducts = ref<any[]>([]);
const linkedTotal = ref(0);
const linkedLoading = ref(false);
const linkedQueryParams = reactive({
  pageNum: 1,
  pageSize: 10,
  [props.searchField]: ""
});

const availableProducts = ref<any[]>([]);
const linkTotal = ref(0);
const linkLoading = ref(false);
const linkQueryParams = reactive({
  pageNum: 1,
  pageSize: 10,
  [props.searchField]: ""
});

const selectedLinkedProducts = ref<any[]>([]); // 已关联表格中选中的待移除项
const globalSelectedAvailableProducts = ref<Map<any, any>>(new Map()); // 可关联表格中跨页选中的项
const availableTableRef = ref<any>(null); // 可关联表格的ref

// Methods
const getLinkedProducts = async () => {
  linkedLoading.value = true;
  try {
    const query = {
      targetId: props.targetId,
      pageNum: linkedQueryParams.pageNum,
      pageSize: linkedQueryParams.pageSize,
      [props.searchField]: linkedQueryParams[props.searchField]
    };
    const result: any = await new Promise(resolve => {
      emit("getLinkedItems", query, resolve);
    });

    if (result && result.rows) {
      linkedProducts.value = result.rows;
      linkedTotal.value = result.total;
    } else {
      linkedProducts.value = [];
      linkedTotal.value = 0;
      ElMessage.error("获取已关联项目失败");
    }
  } catch (error) {
    console.error("获取已关联项目失败:", error);
    ElMessage.error("获取已关联项目失败");
  } finally {
    linkedLoading.value = false;
  }
};

// 获取可关联项目
const getAvailableProducts = async () => {
  linkLoading.value = true;
  try {
    const excludeIds = linkedProducts.value.map(item => item[props.idField]);
    const query = {
      pageNum: linkQueryParams.pageNum,
      pageSize: linkQueryParams.pageSize,
      [props.searchField]: linkQueryParams[props.searchField],
      excludeIds: excludeIds
    };
    const result: any = await new Promise(resolve => {
      emit("getAvailableItems", query, resolve);
    });

    if (result && result.rows) {
      availableProducts.value = result.rows;
      linkTotal.value = result.total;
      // 恢复跨页选择
      await nextTick(() => {
        availableProducts.value.forEach(row => {
          if (globalSelectedAvailableProducts.value.has(row[props.idField])) {
            availableTableRef.value?.toggleRowSelection(row, true);
          }
        });
      });
    } else {
      availableProducts.value = [];
      linkTotal.value = 0;
      ElMessage.error("获取可关联项目失败");
    }
  } catch (error) {
    console.error("获取可关联项目失败:", error);
    ElMessage.error("获取可关联项目失败");
  } finally {
    linkLoading.value = false;
  }
};
// 已关联表格选择事件
const handleLinkedSelectionChange = (selection: any[]) => {
  selectedLinkedProducts.value = selection;
};
// 可关联表格选择事件
const handleLinkSelectionChange = (selection: any[]) => {
  // 更新 globalSelectedAvailableProducts
  const currentPageIds = new Set(availableProducts.value.map(item => item[props.idField]));
  // 移除当前页未选中的
  currentPageIds.forEach(id => {
    if (!selection.some(item => item[props.idField] === id)) {
      globalSelectedAvailableProducts.value.delete(id);
    }
  });
  // 添加当前页选中的
  selection.forEach(item => {
    globalSelectedAvailableProducts.value.set(item[props.idField], item);
  });
};

const removeLinkedProduct = async (row: any) => {
  console.log("移除已关联项目:", row);
  ElMessageBox.confirm(`是否确认移除已关联的 "${row.name}"?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(async () => {
      const currentAssociatedIds = linkedProducts.value.map(item => item[props.idField]);
      const newAssociatedIds = currentAssociatedIds.filter(id => id !== row[props.idField]);
      console.log("新关联项目ID:", newAssociatedIds);
      const success = await new Promise(resolve => {
        emit("updateAssociation", { targetId: props.targetId, associatedIds: newAssociatedIds }, resolve);
      });
      if (success) {
        ElMessage.success("移除成功");
        await getLinkedProducts(); // 刷新已关联列表
        await getAvailableProducts(); // 刷新可关联列表
        emit("confirm"); // 通知父组件关联已更新
      } else {
        ElMessage.error("移除失败");
      }
    })
    .catch(() => {});
};

const batchRemoveLinkedProducts = async () => {
  if (selectedLinkedProducts.value.length === 0) {
    ElMessage.warning("请选择要移除的项目");
    return;
  }
  ElMessageBox.confirm(`是否确认批量移除选中的 ${selectedLinkedProducts.value.length} 个项目?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(async () => {
      const selectedIdsToRemove = selectedLinkedProducts.value.map(item => item[props.idField]);
      const success = await new Promise(resolve => {
        emit(
          "removeAssociation",
          {
            targetId: props.targetId,
            associatedIds: selectedIdsToRemove,
            operation: "remove"
          },
          resolve
        );
      });
      if (success) {
        ElMessage.success("批量移除成功");
        await getLinkedProducts();
        await getAvailableProducts();
        selectedLinkedProducts.value = []; // 清空选择
        emit("confirm");
      } else {
        ElMessage.error("批量移除失败");
      }
    })
    .catch(() => {});
};

// 确认关联操作
const confirmLink = async () => {
  if (globalSelectedAvailableProducts.value.size === 0) {
    ElMessage.warning("请选择要关联的项目");
    return;
  }

  ElMessageBox.confirm(`是否确认关联选中的 ${globalSelectedAvailableProducts.value.size} 个项目?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(async () => {
      const selectedIdsToAdd = Array.from(globalSelectedAvailableProducts.value.keys());
      const success = await new Promise(resolve => {
        emit(
          "addAssociation",
          {
            targetId: props.targetId,
            associatedIds: selectedIdsToAdd,
            operation: "add"
          },
          resolve
        );
      });
      console.log("关联操作结果:", success);
      if (success) {
        ElMessage.success("关联成功");
        await getLinkedProducts();
        await getAvailableProducts();
        globalSelectedAvailableProducts.value.clear(); // 清空选择
        availableTableRef.value?.clearSelection(); // 清空表格选择
        emit("confirm");
      } else {
        globalSelectedAvailableProducts.value.clear(); // 清空选择
        availableTableRef.value?.clearSelection(); // 清空表格选择
        ElMessage.error("关联失败");
      }
    })
    .catch(() => {});
};

const cancelLink = () => {
  emit("update:modelValue", false); // 关闭对话框
  globalSelectedAvailableProducts.value.clear(); // 清空选择
  selectedLinkedProducts.value = [];
  availableTableRef.value?.clearSelection();
  emit("cancel");
};

const handleClose = () => {
  emit("update:modelValue", false); // 确保关闭时触发 update:modelValue
  globalSelectedAvailableProducts.value.clear();
  selectedLinkedProducts.value = [];
  availableTableRef.value?.clearSelection();
  // 不触发 cancel 事件，因为用户可能只是点击了关闭按钮
};

const handleLinkedQuery = () => {
  linkedQueryParams.pageNum = 1;
  getLinkedProducts();
};

const handleLinkQuery = () => {
  linkQueryParams.pageNum = 1;
  getAvailableProducts();
};

// Watchers
watch(
  () => props.modelValue,
  newVal => {
    if (newVal) {
      // 重置查询参数和选择状态
      linkedQueryParams.pageNum = 1;
      linkedQueryParams[props.searchField] = "";
      linkQueryParams.pageNum = 1;
      linkQueryParams[props.searchField] = "";
      globalSelectedAvailableProducts.value.clear();
      selectedLinkedProducts.value = [];
      nextTick(() => {
        availableTableRef.value?.clearSelection();
      });

      // 确保 targetId 存在才加载数据
      if (props.targetId !== null) {
        getLinkedProducts();
        getAvailableProducts();
      } else {
        ElMessage.warning("未提供目标ID，无法加载关联数据");
      }
    }
  }
);
</script>

<style scoped lang="scss">
.selection-info {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-bottom: 15px;
  font-size: 14px;
  color: #606266;

  span {
    margin-left: 20px;
  }

  .selection-detail {
    font-weight: bold;
    color: #409eff;
  }
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 10px;
  margin-bottom: 15px;
  border-bottom: 1px solid #ebeef5;

  h3 {
    margin: 0;
    font-size: 16px;
    color: #303133;
  }

  .search-form {
    display: flex;
    gap: 10px;
    align-items: center;
    margin-bottom: 0;

    .el-form-item {
      margin-bottom: 0;
    }
  }
}

.linked-products-section,
.available-products-section {
  display: flex;
  flex-direction: column;
  height: 550px; /* 固定高度，确保表格和分页在容器内 */
  padding: 15px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}

.linked-table,
.available-table {
  flex: 1; /* 让表格占据剩余空间 */
  overflow: auto; /* 确保表格内容可滚动 */
}

.el-pagination {
  justify-content: flex-end;
  margin-top: 15px;
}

.dialog-footer {
  padding-top: 20px;
  text-align: right;
  border-top: 1px solid #ebeef5;
}
</style>
